// 引入线宽设置相关库
import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry.js';
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js';
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js';
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2.js';
import { Line2 } from 'three/examples/jsm/lines/Line2.js';
import * as THREE from 'three';




// xz 二维数组转三维  y值为0 (俯视)
const pointArrToVector3 = (pointArr = []) => {
    // ep :  pointArr = [ [100, 0], [100, -80] ]
    const arr = pointArr.map(item => {
        return new THREE.Vector3(item[0], 0, item[1])
    })
    return arr;
}
// vec3数组转换成普通数组 3个坐标一组
const vector3ArrToNormal = (vector3Arr = []) => {
    const arr = []
    vector3Arr.forEach(item => arr.push(item.x, item.y, item.z))
    return arr
}


/**
 * 创建线条
 * @param {*} pointArr 二维数组 xz的点位 如 [ [100, 0], [100, -80] ]
 * @param {*} pointNumber 分段数  分段数越多 点数越多 飞线越慢
 * @param {*} color 线段颜色
 * @param {*} linewidth 线段宽度
 * @returns 
 */
const createLine = (pointArr = [], pointNumber = 100, color = 0xff2000, linewidth = 2) => {
    const geometry = new LineGeometry(); //创建一个缓冲类型几何体
    const lineArr = pointArrToVector3(pointArr)
    const curve = new THREE.CatmullRomCurve3([
        ...lineArr
    ], false, 'catmullrom', 0);
    const points = curve.getPoints(pointNumber); //分段数100，返回101个顶点
    const lineList = vector3ArrToNormal(points)
    geometry.setPositions(lineList);
    const material = new LineMaterial({
        linewidth,
        color, //轨迹颜色
    });
    material.resolution.set(window.innerWidth, window.innerHeight);
    const line = new Line2(geometry, material);
    line.points = points
    return line
}

/**
 * 创建飞线 
// 
 * @param {*} points  飞线属于哪个线段
 * @param {*} index  飞线起始位置
 * @param {*} number 
 * @returns 
 */
const createFlyLine = (points, index = 0, number = 20, dividerNumber = 50) => {
    // console.log('points', points);
    const list = points.slice(index, index + number);

    const curve = new THREE.CatmullRomCurve3(list, false, 'catmullrom', 0);
    const points2 = curve.getPoints(dividerNumber);
    const geometry = new THREE.BufferGeometry();
    geometry.setFromPoints(points2);

    const percentArr = []; //attributes.percent的数据
    for (let i = 0; i < points2.length; i++) {
        percentArr.push(i / points2.length);
    }
    const percentAttribue = new THREE.BufferAttribute(new Float32Array(percentArr), 1);
    geometry.attributes.percent = percentAttribue;

    // 批量计算所有顶点颜色数据
    const colorArr = [];
    for (let i = 0; i < points2.length; i++) {
        let color1 = new THREE.Color(0xff2000); //轨迹线颜色 青色
        let color2 = new THREE.Color(0xffff00); //黄色
        let color = color1.lerp(color2, i / points2.length)
        colorArr.push(color.r, color.g, color.b);
    }

    // 设置几何体顶点颜色数据
    geometry.attributes.color = new THREE.BufferAttribute(new Float32Array(colorArr), 3);


    // 点模型渲染几何体每个顶点
    const PointsMaterial = new THREE.PointsMaterial({
        // color: 0xffff00,
        size: 2, //点大小
        vertexColors: true, //使用顶点颜色渲染
    });

    PointsMaterial.onBeforeCompile = (shader) => {
        // 顶点着色器中声明一个attribute变量:百分比
        shader.vertexShader = shader.vertexShader.replace(
            'void main() {',
            [
                'attribute float percent;', //顶点大小百分比变量，控制点渲染大小
                'void main() {',
            ].join('\n') // .join()把数组元素合成字符串
        );
        // 调整点渲染大小计算方式
        shader.vertexShader = shader.vertexShader.replace(
            'gl_PointSize = size;',
            [
                'gl_PointSize = percent * size;',
            ].join('\n') // .join()把数组元素合成字符串
        );
    };


    const flyPoints = new THREE.Points(geometry, PointsMaterial);
    // 用于循环渲染所有飞线
    flyPoints.index = index //每条飞线的起点
    flyPoints.number = number //每条飞线长度
    flyPoints.dividerNumber = dividerNumber //每条飞线拆分的点
    flyPoints.indexMax = points.length - number // 每条飞线最多能跑的点数 超过归零循环
    flyPoints.points = points //每条飞线途径的路径点
    return flyPoints
}
export default {
    createLine,
    createFlyLine
}
